package controller

import (
	"encoding/json"
	"errors"
	"file-download-server/service"
	"file-download-server/util"
	"file-download-server/vo"
	"net/http"
)

type FileController struct {
	Service *service.FileService
}

func NewFileController(s *service.FileService) *FileController {
	return &FileController{Service: s}
}

// UploadHandler 上传文件（后端自动分片）
func (fc *FileController) UploadHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.UploadRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}
	if req.ChunkSize <= 0 {
		req.ChunkSize = service.DefaultChunkSize // 默认 1MB
	}

	task, err := fc.Service.UploadFile(req.FilePath, req.ChunkSize)
	if err != nil {
		switch {
		case errors.Is(err, service.ErrFileNotFound):
			util.ToJSONResponse(w, util.FileUploadSourceMissing, err.Error(), nil)
		case errors.Is(err, service.ErrInvalidParams):
			util.ToJSONResponse(w, util.FileInvalidUploadParams, err.Error(), nil)
		default:
			util.ToJSONResponse(w, util.FileUploadProcessingFailed, err.Error(), nil)
		}
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "上传成功", task)
}

// DownloadHandler 下载文件（后端自动分片）
func (fc *FileController) DownloadHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.DownloadRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}
	if req.ChunkSize <= 0 {
		req.ChunkSize = service.DefaultChunkSize // 默认1MB
	}
	task, err := fc.Service.DownloadFile(req.FileName, req.ChunkSize, req.SavePath)
	if err != nil {
		switch {
		case errors.Is(err, service.ErrFileNotFound):
			util.ToJSONResponse(w, util.FileDownloadSourceMissing, err.Error(), nil)
		default:
			util.ToJSONResponse(w, util.FileDownloadProcessingFailed, err.Error(), nil)
		}
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "下载成功", task)
}

// ListTasksHandler 获取任务列表
func (fc *FileController) ListTasksHandler(w http.ResponseWriter, r *http.Request) {
	tasks := fc.Service.ListTasks()
	util.ToJSONResponse(w, util.FileSuccess, "任务列表", tasks)
}

// GetTaskHandler 获取任务详情
func (fc *FileController) GetTaskHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.GetTaskRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}

	task, err := fc.Service.GetTask(req.TaskID)
	if err != nil {
		if errors.Is(err, service.ErrTaskNotFound) {
			util.ToJSONResponse(w, util.FileTaskNotFound, err.Error(), nil)
		} else {
			util.ToJSONResponse(w, util.FileTaskQueryFailed, err.Error(), nil)
		}
		return
	}
	util.ToJSONResponse(w, util.FileSuccess, "任务详情", task)
}

// ListFilesHandler 获取upload目录下的所有文件（分页）
func (fc *FileController) ListFilesHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.ListFilesRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		req.Page = 1
		req.PageSize = 10
	}

	resp, err := fc.Service.ListUploadedFiles(req.Page, req.PageSize)
	if err != nil {
		util.ToJSONResponse(w, util.FileListFilesFailed, err.Error(), nil)
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "文件列表", resp)
}

// UpdateFileHandler 修改已上传文件名
func (fc *FileController) UpdateFileHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.UpdateFileRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}

	if req.OldFileName == "" || req.NewFileName == "" {
		util.ToJSONResponse(w, util.FileMissingRequiredField, "必须指定原文件名和新文件名", nil)
		return
	}

	if err := fc.Service.UpdateFile(req); err != nil {
		switch {
		case errors.Is(err, service.ErrFileNotFound):
			util.ToJSONResponse(w, util.FileFileNotFound, err.Error(), nil)
		case errors.Is(err, service.ErrInvalidParams):
			util.ToJSONResponse(w, util.FileFileRenameConflict, err.Error(), nil)
		default:
			util.ToJSONResponse(w, util.FileUpdateFileFailed, err.Error(), nil)
		}
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "文件重命名成功", nil)
}

// DeleteTaskHandler 删除任务（清理下载分片）
func (fc *FileController) DeleteTaskHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.DeleteTaskRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}

	if err := fc.Service.DeleteTask(req.TaskID); err != nil {
		if errors.Is(err, service.ErrTaskNotFound) {
			util.ToJSONResponse(w, util.FileTaskNotFound, err.Error(), nil)
		} else {
			util.ToJSONResponse(w, util.FileTaskDeletionFailed, err.Error(), nil)
		}
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "任务删除成功", nil)
}

// DeleteFileHandler 删除物理文件
func (fc *FileController) DeleteFileHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.DeleteFileRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}

	if err := fc.Service.DeleteUploadFile(req.FileName); err != nil {
		if errors.Is(err, service.ErrFileNotFound) {
			util.ToJSONResponse(w, util.FileFileNotFound, err.Error(), nil)
		} else {
			util.ToJSONResponse(w, util.FileFileDeletionFailed, err.Error(), nil)
		}
		return
	}

	util.ToJSONResponse(w, util.FileSuccess, "文件删除成功", nil)
}

// DownloadFromURLHandler 指定url然后下载文件
func (fc *FileController) DownloadFromURLHandler(w http.ResponseWriter, r *http.Request) {
	var req vo.DownloadFromURLRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.ToJSONResponse(w, util.FileInvalidJSON, "请求参数错误", nil)
		return
	}

	task, err := fc.Service.DownloadFromURLWithRange(req)
	if err != nil {
		switch {
		case errors.Is(err, service.ErrInvalidParams):
			util.ToJSONResponse(w, util.FileInvalidRemoteURLParams, err.Error(), task)
		case errors.Is(err, service.ErrFileNotFound):
			util.ToJSONResponse(w, util.FileDownloadSourceMissing, err.Error(), task)
		default:
			util.ToJSONResponse(w, util.FileRemoteDownloadFailed, err.Error(), task)
		}
		return
	}
	util.ToJSONResponse(w, util.FileSuccess, "远程分块下载任务完成", task)
}
